# from socket import socket, SOCK_STREAM, AF_INET
from datetime import datetime
import time
import tkinter as tk
from tkinter import scrolledtext
from tkinter import messagebox
from tkinter import filedialog
from threading import Thread
from contextlib import contextmanager
import json

# import time
import traceback
from utils import process_logger, DateEncoder


class serverframe(tk.Frame):
    def __init__(self, root, op_queue, info_queue, usr_info):
        tk.Frame.__init__(self, root)
        self.op_queue = op_queue
        self.info_queue = info_queue
        self.usr_info = usr_info
        self.root = root
        self.create_frame()
        self.pack_frame()

        Thread(target=self.check_queue, daemon=True).start()

    def create_frame(self):
        self.topper = tk.Frame(self, borderwidth=2)
        self.tailer = tk.Frame(self)
        self.body = tk.Frame(self)
        self.lb_con_text = tk.StringVar(value="IDLE")
        self.lb_con = tk.Label(
            self.topper,
            textvariable=self.lb_con_text,
            bg="yellowgreen",
            width=20,
        )
        self.lb_ip = tk.Label(self.topper, text="IP:")
        self.lb_port = tk.Label(self.topper, text="PORT:")
        self.et_ip_text = tk.StringVar(value="localhost")
        self.et_port_text = tk.StringVar(value="6789")

        self.et_ip = tk.Entry(
            self.topper, width=20, textvariable=self.et_ip_text
        )
        self.et_port = tk.Entry(
            self.topper, width=20, textvariable=self.et_port_text
        )
        self.bt_lis = tk.Button(
            self.topper,
            text="Listen",
            command=self.lis_start,
        )
        self.bt_break = tk.Button(
            self.topper,
            text="Break",
            command=self.lis_stop,
        )
        self.usr_ls = tk.Listbox(self.body)

        self.tx_dialog = scrolledtext.ScrolledText(
            self.body, width=100, height=10, state="disabled"
        )
        self.tx_input = tk.Text(self.body, width=100, height=5)
        self.tx_dialog.tag_config("server", foreground="red")
        self.tx_dialog.tag_config("client", foreground="blue")
        self.bt_send = tk.Button(
            self.tailer,
            width=10,
            heigh=2,
            text="Send",
            command=self.sendInputMsg,
        )
        self.bt_file = tk.Button(
            self.tailer,
            width=10,
            heigh=2,
            text="File",
            command=self.sendFile,
        )

    def pack_frame(self):
        self.topper.pack(side="top", pady=10, padx=10)
        self.lb_con.pack(side="left", padx=10)
        self.lb_ip.pack(side="left")
        self.et_ip.pack(side="left", padx=10)
        self.lb_port.pack(side="left")
        self.et_port.pack(side="left", padx=10)
        self.bt_lis.pack(side="left")
        self.bt_break.pack(side="left")

        self.usr_ls.pack(side="left")
        self.tx_dialog.pack(side="top", pady=5, padx=5)
        self.tx_input.pack(side="top", pady=5, padx=5)
        self.body.pack()
        self.bt_send.pack(side="left")
        self.bt_file.pack(side="left")
        self.tailer.pack()
        self.pack()

    def check_queue(self):
        while True:
            while not self.info_queue.empty():
                info = self.info_queue.get()
                print(info)
                if isinstance(info, str):
                    self.tx_dialog.delete(0.0, "END")
                else:
                    eval("self." + info[0]).set(info[1])
            time.sleep(0)

    def lis_start(self):
        self.op_queue.put(
            (
                "lis_start",
                {
                    "port": self.et_ip_text.get(),
                    "ip": int(self.et_port_text.get()),
                },
            )
        )
        with self.dialog_manager():
            self.tx_dialog.delete(0.0, tk.END)
        self.lb_con_text.set("Listening...")

    def lis_stop(self):
        self.op_queue.put(("lis_stop", {}))
        if self.lb_con_text.get() != "Client Exit":
            self.lb_con_text.set("IDLE")
        with self.dialog_manager():
            self.tx_dialog.delete(0.0, tk.END)

    @process_logger
    def showMsg(self, msg_item):
        # 显示发送时间和发送消息
        with self.dialog_manager():
            sender = (
                "server"
                if msg_item["type"] == 0 or msg_item["type"] == 2
                else "client"
            )
            timemsg = (
                (
                    self.usr_info[msg_item["user_id"]]
                    if not msg_item["type"] % 2 == 0
                    else "server"
                )
                + ":"
                + msg_item["time"].strftime("%Y-%m-%d %H:%M:%S")
                + "\n"
            )
            self.tx_dialog.insert(tk.END, timemsg, sender)
            self.tx_dialog.insert(tk.END, str(msg_item["msg"]) + "\n")
        self.tx_dialog.see(tk.END)

    @process_logger
    def sendInputMsg(self):
        msg = self.tx_input.get("1.0", "end-1c")
        if msg != "":
            # 显示发送时间和发送消息
            self.op_queue.put(
                (
                    "sendMsg",
                    {
                        "type": 0,
                        "user_id": list(self.usr_info.keys())[
                            self.usr_ls.curselection()[0]
                        ],
                        "msg": msg,
                    },
                )
            )
            self.tx_input.delete(0.0, tk.END)  # 删除输入框的内容
        else:
            messagebox.showinfo("警告", "不能发送空白信息！")

    @process_logger
    def sendFile(self):
        select_files = filedialog.askopenfilenames(
            title="可选择1个或多个文件"
        )  # askopenfilename 1次上传1个；askopenfilenames1次上传多个
        self.op_queue.put(
            ("sendFile", {"select_files": select_files})
        )

    @process_logger
    def addFriend(self, usr_id):
        self.op_queue.put(
            (
                "addFriend",
                {
                    "usr_1": list(self.usr_info.keys())[
                        self.usr_ls.curselection()[0]
                    ],
                    "usr_2": usr_id,
                },
            )
        )

    @process_logger
    def delFriend(self, usr_id):
        self.op_queue.put(
            (
                "delFriend",
                {
                    "usr_1": list(self.usr_info.keys())[
                        self.usr_ls.curselection()[0]
                    ],
                    "usr_2": usr_id,
                },
            )
        )

    @contextmanager
    def dialog_manager(self):
        self.tx_dialog.config(state="normal")
        yield
        self.tx_dialog.config(state="disabled")
